const fs = require('fs');
const path = require('path');
const { exec } = require('child_process');

// 配置
const config = {
    startDirectory: process.cwd(), // 从当前目录开始，可以修改为其他路径
    excludePaths: [],             // 可以添加要排除的特定路径
    openFolders: true,           // 是否打开包含 node_modules 的文件夹
    verbose: true                // 显示详细日志
};

// 存储找到的 node_modules 路径
const nodeModulesPaths = [];

/**
 * 检查路径是否应该被排除
 * @param {string} targetPath 要检查的路径
 * @returns {boolean} 如果路径应该被排除则返回 true
 */
function shouldExclude(targetPath) {
    return config.excludePaths.some(excludedPath =>
        path.resolve(targetPath).startsWith(path.resolve(excludedPath))
    );
}

/**
 * 使用系统默认文件管理器打开文件夹
 * @param {string} folderPath 要打开的文件夹路径
 */
function openFolder(folderPath) {
    let command;
    switch (process.platform) {
        case 'darwin': // macOS
            command = `open "${folderPath}"`;
            break;
        case 'win32': // Windows
            command = `explorer "${folderPath}"`;
            break;
        case 'linux': // Linux
            command = `xdg-open "${folderPath}"`;
            break;
        default:
            console.log(`不支持自动打开文件夹的操作系统: ${process.platform}`);
            return;
    }

    exec(command, (error) => {
        if (error) {
            console.error(`打开文件夹失败: ${folderPath}`, error);
        } else {
            console.log(`已打开文件夹: ${folderPath}`);
        }
    });
}

/**
 * 遍历目录查找所有 node_modules 文件夹
 * @param {string} dirPath 要遍历的目录路径
 */
function findNodeModules(dirPath) {
    if (shouldExclude(dirPath)) {
        config.verbose && console.log(`[跳过] 排除的目录: ${dirPath}`);
        return;
    }

    if (!fs.existsSync(dirPath)) {
        console.log(`[警告] 目录不存在: ${dirPath}`);
        return;
    }

    try {
        const files = fs.readdirSync(dirPath);

        for (const file of files) {
            const fullPath = path.join(dirPath, file);

            try {
                const stat = fs.lstatSync(fullPath);

                if (stat.isDirectory()) {
                    if (file === 'node_modules') {
                        // 找到 node_modules 目录
                        const parentFolder = dirPath; // node_modules 所在的父文件夹
                        nodeModulesPaths.push(parentFolder);

                        console.log(`[找到] node_modules 位于: ${parentFolder}`);

                        // 打开包含 node_modules 的文件夹
                        if (config.openFolders) {
                            openFolder(parentFolder);
                        }

                        // 不遍历 node_modules 内部的子目录
                        continue;
                    }

                    // 递归遍历其他目录
                    findNodeModules(fullPath);
                }
            } catch (err) {
                console.error(`[错误] 访问 ${fullPath} 失败:`, err.message);
            }
        }
    } catch (err) {
        console.error(`[错误] 读取目录 ${dirPath} 失败:`, err.message);
    }
}

// 主程序
function main() {
    console.log('========================================');
    console.log('Node.js 查找并打开 node_modules 所在文件夹');
    console.log(`开始目录: ${config.startDirectory}`);
    console.log(`排除路径: ${config.excludePaths.join(', ') || '无'}`);
    console.log(`自动打开文件夹: ${config.openFolders ? '是' : '否'}`);
    console.log('========================================\n');

    // 开始查找
    findNodeModules(config.startDirectory);

    // 输出结果
    console.log('\n查找完成');
    console.log(`共找到 ${nodeModulesPaths.length} 个 node_modules 文件夹`);

    if (nodeModulesPaths.length > 0) {
        console.log('\n找到的 node_modules 所在文件夹:');
        nodeModulesPaths.forEach((p, i) => console.log(`${i + 1}. ${p}`));
    }
}

main();